#include "dring_buffer.h"

using namespace std;
using namespace dutils;

dring_buffer::dring_buffer(int capacity)
    :m_capacity(capacity),
    m_buffer(NULL)
{
    m_buffer = new unsigned char[m_capacity + 1];
    memset(m_buffer, 0x00, m_capacity + 1);
}

dring_buffer::~dring_buffer()
{
    if (NULL != m_buffer)
    {
        delete[] m_buffer;
        m_buffer = NULL;
    }
}

int dring_buffer::capacity()
{
    int ret = 0;
    ret = m_capacity;
    return ret;
}

int dring_buffer::size()
{
    int ret = 0;

    m_lock.lock();
    ret = m_size;
    m_lock.unlock();

    return ret;
}

int dring_buffer::left_space()
{
    int ret;

    m_lock.lock();
    ret = m_capacity - m_size;
    m_lock.unlock();

    return ret;
}

int dring_buffer::push(unsigned char* data, int data_size)
{
    int ret = 0;
    if ((NULL == data) || (data_size <= 0) || (left_space() < data_size))
    {
        return ret;
    }

    m_lock.lock();
    for (int i = 0; i < data_size; i++)
    {
        m_buffer[m_head] = data[i];
        m_head = (m_head++) % m_capacity;

        m_size++;
    }
    ret = data_size;
    m_lock.unlock();

    return ret;
}

int dring_buffer::pop(unsigned char* data, int data_size)
{
    int ret = 0;
    if ((NULL == data) || (data_size <=0) || (size() < data_size))
    {
        return ret;
    }

    m_lock.lock();
    for (int i = 0; i < data_size; i++)
    {
        data[i] = m_buffer[m_tail];
        m_buffer[m_tail] = '\0';
        m_tail = (m_tail++) % m_capacity;

        m_size--;
    }
    ret = data_size;
    m_lock.unlock();

    return ret;
}

void dring_buffer::clean()
{
    m_lock.lock();
    m_head = m_tail = 0;
    m_lock.unlock();
}